/* -*-C-*-
 ##############################################################################
 #
 # File:        trice/src/testdata.c
 # RCS:         "@(#)$Revision: 1.16 $ $Date: 94/03/09 11:14:10 $"
 # Description: Diagnostic routines for data i/o
 # Author:      Doug Passey
 # Created:     
 # Language:    C
 # Package:     E1430
 # Status:      "@(#)$State: Exp $"
 #
 # (C) Copyright 1992, Hewlett-Packard Company, all rights reserved.
 #
 ##############################################################################
 #
 # Please add additional comments here
 #
 # Revisions:
 #
 ##############################################################################
*/

#    include <stdio.h>

#include "trice.h"
#include "err1430.h"

#ifndef lint
const char i1430_testdata_fileId[] = "$Header: testdata.c,v 1.16 94/03/09 11:14:10 chriss Exp $";
#endif


#define REAL_MSW	0xDD
#define IMAG_MSW	0x0
#define IMAG_MSW16	0x1
#define REAL_LSW	0xEAC0
#define IMAG_LSW	0x0

#define NUM_SAMPLES	64

/*****************************************************************************
 *
 * Check the ability of the module to collect data and output the results
 * with the correct data format.
 *
 ****************************************************************************/
SHORTSIZ16 e1430_test_data_collection(SHORTSIZ16 la) 
{
  SHORTSIZ16 error, i, j, start, data;
  volatile SHORTSIZ16 reg;
  SHORTSIZ16 flag = 0;
  SHORTSIZ16 count, pass1, pass2;
  SHORTSIZ16 pass[NUM_SAMPLES], trig[NUM_SAMPLES];
  char buf1[80], buf2[80];
  LONGSIZ32 phase, temp;
  SHORTSIZ16 groupID;

  groupID = e1430_create_module_group(1, &la);

  (void)sprintf(buf1, "%d", (LONGSIZ32)la);

  error = e1430_reset_module(groupID);		/* reset the module */
  if(error) return(error);

  /* first test module to see if it outputs correct constant data */

  /* ADC in diagnostic mode to output a constant */
  error = e1430_write_register_card(la, E1430_ADC_CONTROL_REG, 
	ADC_CONTROL_CAL_MODE_1 | ADC_CONTROL_DIAG_GAIN_ERR);
  if(error) return(error);

  /*  set blocksize to NUM_SAMPLES (2 bytes per sample ) */
  reg = NUM_SAMPLES/4;		/* number of samples in 8 byte chunk */
  for(i=-1; reg > 0; i++) {	/* calculate N in 8 * 2^N */
    reg >>= 1;
  }

  reg = i << TRIGGER_BLOCKSIZE_BIT_SHIFT;
  error = e1430_write_register_card(la, E1430_TRIGGER_BLOCKSIZE_REG, reg);
  if(error) return(error);


  /* 16-bit real block mode */
  error = e1430_write_register_card(la, E1430_DATA_FORMAT_REG, 
	DATA_FORMAT_DATA_TYPE_REAL | DATA_FORMAT_DATA_SIZE_16 |
	DATA_FORMAT_BLOCK_MODE_ON);
  if(error) return(error);

  /* start the measurement and wait for data to be ready */
  error = i1430_start_meas_and_wait(la);
  if(error) return(error);

  /* check for valid data */
  for(i=0; i<NUM_SAMPLES; i++) {
    error = e1430_read_register_card(la, E1430_HP_SEND_DATA_REG, &data);
    if(error) return(error);

    if(data != (SHORTSIZ16)REAL_MSW) {
      flag = 1;
    }
  }

  /* check that only NUM_SAMPLES data points are in record */
  e1430_addr = e1430_get_register_address(la, E1430_HP_SEND_DATA_REG);
  E1430_TRY 

    for(e1430_i=0; e1430_i<2*NUM_SAMPLES; e1430_i++) {
      reg = iwpeek( (USHORTSIZ16 *)e1430_addr );
      E1430_CHECK_BERR
    }

  E1430_RECOVER {
	;			/* should bus error so do nothing */
  }

  if(e1430_i!=0) {		/* illegal extra samples */
    (void)sprintf(buf1, "%d", (LONGSIZ32)NUM_SAMPLES);
    (void)sprintf(buf2, "%d", (LONGSIZ32)(NUM_SAMPLES + e1430_i));
    error = i1430_Error(ERR1430_EXTRA_DATA_WORDS, buf1, buf2);
    if(error) return(error);
  }

  if(flag) {
    error = i1430_Error(ERR1430_REAL_DATA_16, buf1, NULL);
    if(error) return(error);
  }
  
  /* 16-bit complex block mode */
  error = e1430_write_register_card(la, E1430_DATA_FORMAT_REG, 
	DATA_FORMAT_DATA_TYPE_COMPLEX | DATA_FORMAT_DATA_SIZE_16 |
	DATA_FORMAT_BLOCK_MODE_ON);
  if(error) return(error);

  /* start the measurement and wait for data to be ready */
  error = i1430_start_meas_and_wait(la);
  if(error) return(error);

  /* check for valid data */
  for(i=0; i<2; i++) {
    error = e1430_read_register_card(la, E1430_HP_SEND_DATA_REG, &data);
    if(error) return(error);
    
    if(data != (SHORTSIZ16)REAL_MSW) {
      flag = 1;
    }
    
    error = e1430_read_register_card(la, E1430_HP_SEND_DATA_REG, &data);
    if(error) return(error);
    
    if(data != (SHORTSIZ16)IMAG_MSW16) {
      flag = 1;
    }
  }

  if(flag) {
    error = i1430_Error(ERR1430_COMPLEX_DATA_16, buf1, NULL);
    if(error) return(error);
  }

  
  /* 32-bit real block mode */
  error = e1430_write_register_card(la, E1430_DATA_FORMAT_REG, 
	DATA_FORMAT_DATA_TYPE_REAL | DATA_FORMAT_DATA_SIZE_32 |
	DATA_FORMAT_BLOCK_MODE_ON);
  if(error) return(error);

  /* start the measurement and wait for data to be ready */
  error = i1430_start_meas_and_wait(la);
  if(error) return(error);

  /* check for valid data */
  for(i=0; i<2; i++) {
    error = e1430_read_register_card(la, E1430_HP_SEND_DATA_REG, &data);
    if(error) return(error);
    
    if(data != (SHORTSIZ16)REAL_MSW) {
      flag = 1;
    }
    
    error = e1430_read_register_card(la, E1430_HP_SEND_DATA_REG, &data);
    if(error) return(error);
    
    if(data != (SHORTSIZ16)REAL_LSW) {
      flag = 1;
    }
  }

  if(flag) {
    error = i1430_Error(ERR1430_REAL_DATA_32, buf1, NULL);
    if(error) return(error);
  }

  
  /* 32-bit complex block mode */
  error = e1430_write_register_card(la, E1430_DATA_FORMAT_REG, 
	DATA_FORMAT_DATA_TYPE_COMPLEX | DATA_FORMAT_DATA_SIZE_32 |
	DATA_FORMAT_BLOCK_MODE_ON);
  if(error) return(error);

  /* start the measurement and wait for data to be ready */
  error = i1430_start_meas_and_wait(la);
  if(error) return(error);

  /* check for valid data */
  error = e1430_read_register_card(la, E1430_HP_SEND_DATA_REG, &data);
  if(error) return(error);
    
  if(data != (SHORTSIZ16)REAL_MSW) {
    flag = 1;
  }
    
  error = e1430_read_register_card(la, E1430_HP_SEND_DATA_REG, &data);
  if(error) return(error);
  
  if(data != (SHORTSIZ16)REAL_LSW) {
    flag = 1;
  }

  error = e1430_read_register_card(la, E1430_HP_SEND_DATA_REG, &data);
  if(error) return(error);
    
  if(data != (SHORTSIZ16)IMAG_MSW) {
    flag = 1;
  }
    
  error = e1430_read_register_card(la, E1430_HP_SEND_DATA_REG, &data);
  if(error) return(error);
  
  if(data != (SHORTSIZ16)IMAG_LSW) {
    flag = 1;
  }

  if(flag) {
    error = i1430_Error(ERR1430_COMPLEX_DATA_32, buf1, NULL);
    if(error) return(error);
  }

  /* check that the passtags contain only data in the lower 5 bits */

  /*  set blocksize to NUM_SAMPLES (4 bytes per sample ) */
  reg = NUM_SAMPLES/2;		/* number of samples in 8 byte chunk */
  for(i=-1; reg > 0; i++) {	/* calculate N in 8 * 2^N */
    reg >>= 1;
  }

  reg = i << TRIGGER_BLOCKSIZE_BIT_SHIFT;
  error = e1430_write_register_card(la, E1430_TRIGGER_BLOCKSIZE_REG, reg);
  if(error) return(error);

  /* Check 16-bit real multipass mode >= pass 4 */
  error = e1430_write_register_card(la, E1430_DATA_FORMAT_REG, 
	DATA_FORMAT_DATA_TYPE_REAL | DATA_FORMAT_DATA_SIZE_16 |
	DATA_FORMAT_FILTER_MULTIPASS | DATA_FORMAT_BLOCK_MODE_ON | 
	4 << DATA_FORMAT_PASSOUT_BIT_SHIFT);
  if(error) return(error);

  error = e1430_write_register_card(la, E1430_TRIGGER_PASSOUT_REG, 1);
  if(error) return(error);

  /* start the measurement and wait for data to be ready */
  error = i1430_start_meas_and_wait(la);
  if(error) return(error);

  /* check for valid data */
  error = e1430_read_register_card(la, E1430_HP_SEND_DATA_REG, &data);
  if(error) return(error);
  error = e1430_read_register_card(la, E1430_HP_SEND_DATA_REG, &data);
  if(error) return(error);
  
  pass1 = data & 0x1F;		/* mask all but tag bits */
  if((data & pass1) != data) {  /* tag in lower 5-bits, rest is 0's */
    flag = 1;
  }

  error = e1430_read_register_card(la, E1430_HP_SEND_DATA_REG, &data);
  if(error) return(error);
  error = e1430_read_register_card(la, E1430_HP_SEND_DATA_REG, &data);
  if(error) return(error);

  pass2 = data & 0x1F;		/* mask all but tag bits */
  if((data & pass2) != data) {  /* tag in lower 5-bits, rest is 0's */
    flag = 1;
  }

  if(pass1 == 4) {
    if(pass2 <= 4) {
      flag = 1;
    }
  }else if(pass1 > 4) {
    if(pass2 != 4) {
      flag = 1;
    }
  }else{
    flag = 1;
  }

  if(flag) {
    error = i1430_Error(ERR1430_MULTIPASS_DATA, buf1, NULL);
    if(error) return(error);
  }


  /* check the expected sequence of pass tags calculated from the trigger
   * phase register, with the actual pass tags for the block of data 
   */
  error = e1430_write_register_card(la, E1430_DATA_FORMAT_REG, 
	DATA_FORMAT_DATA_TYPE_REAL | DATA_FORMAT_DATA_SIZE_16 |
	DATA_FORMAT_FILTER_MULTIPASS | DATA_FORMAT_BLOCK_MODE_ON | 
	4 << DATA_FORMAT_PASSOUT_BIT_SHIFT); 
  if(error) return(error);

  /* start the measurement and wait for data to be ready */
  error = i1430_start_meas_and_wait(la);
  if(error) return(error);

  error = i1430_get_trigger_phase_bits(la, &phase);
  if(error) return(error);

  /* get passtags */
  for(i=0; i<NUM_SAMPLES; i++) {
    /* throw away first word which is actual data */
    error = e1430_read_register_card(la, E1430_HP_SEND_DATA_REG, &data);
    if(error) return(error);
    /* get pass tag in 2nd word */
    error = e1430_read_register_card(la, E1430_HP_SEND_DATA_REG, &data);
    if(error) return(error);
    pass[i] = data & 0x1F;
  }

  /* calculate expected passtag sequence from trig delay start */

  /* the SHIFT bits should be 0 or 2, which will adjust the trigger delay
   * by 0 or 1 respectively; get the shift bits 
   */
  (void)e1430_read_register_card(la, E1430_DECIMATION_CNTLAT_0_REG, &start);
  start = (start & 0x300) >> 9;		/* start = 0 or 1 */

  /* adjust phase bits for delay through hardware */
  phase += (1L << 25) + PHASE_DELAY; 
  phase %= (1L << 25);

 
  phase >>= 3;		/* get pass 4 bit to LSB */
  phase -= start;	/* correct for packing in memory */

  /* fill pass tag array calculated from trigger phase */
  for(i=0; i<NUM_SAMPLES; i++) {
    temp = phase++;
    for(j=4; j<32; j++) {  /* find first zero on right */
      if(temp%2 == 0) break;
      temp >>= 1;
    }
    trig[i] = j;
  }

  for(i=0; i<NUM_SAMPLES; i++) {
    if(pass[i] != trig[i]) {

#if 0
    printf("pass[] = ");
    for(i=0; i<NUM_SAMPLES; i++) { 
      printf("%hd ", pass[i]);
    }
    printf("\n");
      
    printf("trig[] = ");
    for(i=0; i<NUM_SAMPLES + 4; i++) { 
	printf("%hd ", trig[i]);
    }
    printf("\n");
#endif 

      error = i1430_Error(ERR1430_DECIMATION_PATTERN, buf1, NULL);
      if(error) return(error);
    }
  } 


  /* Switch to 32-bit, real, multipass=4, with 24-bit passtag & append status */
  error = e1430_write_register_card(la, E1430_DATA_FORMAT_REG, 
	DATA_FORMAT_DATA_TYPE_REAL | DATA_FORMAT_DATA_SIZE_32 |
	DATA_FORMAT_FILTER_MULTIPASS | DATA_FORMAT_BLOCK_MODE_ON | 
 	(4 << DATA_FORMAT_PASSOUT_BIT_SHIFT) | DATA_FORMAT_PASSTAG_24 |
	DATA_FORMAT_APPEND_STATUS_ON);
  if(error) return(error);

  /* start the measurement and wait for data to be ready */
  error = i1430_start_meas_and_wait(la);
  if(error) return(error);

  count = 0;		/* count how many pass 4 results in the record */

  /* check for valid data */
  for(i=0; i<NUM_SAMPLES; i++) {
    /* throw away first word which is actual data */
    error = e1430_read_register_card(la, E1430_HP_SEND_DATA_REG, &data);
    if(error) return(error);
    /* get 2nd word which contains pass tag */
    error = e1430_read_register_card(la, E1430_HP_SEND_DATA_REG, &data);
    if(error) return(error);

    data = (data >> 8) & 0x1F;	/* move passtag from high byte and mask */
    if(data == 4) count++;
  }

  if(count != NUM_SAMPLES/2) {
    error = i1430_Error(ERR1430_PASSTAG_24, buf1, NULL);
    if(error) return(error);
  }

  E1430_TRY 

    e1430_addr = e1430_get_register_address(la, E1430_HP_SEND_DATA_REG);
    reg = iwpeek( (USHORTSIZ16 *)e1430_addr );
    E1430_CHECK_BERR

  E1430_RECOVER {
    error = i1430_Error(ERR1430_NO_STATUS_BYTE, buf1, NULL);
    if(error) return(error);
  }

  (void)e1430_delete_module_group(groupID);
  
  return (0); 


}


